#include <string.h>
#include <tegra_def.h>
-#define BPMP_TIMEOUT 2
+#define BPMP_TIMEOUT 500 /* 500ms */
static uint32_t channel_base[NR_CHANNELS];
static uint32_t bpmp_init_state = BPMP_INIT_PENDING;
int tegra_bpmp_init(void)
{
- uint32_t val, base;
+ uint32_t val, base, timeout = BPMP_TIMEOUT;
unsigned int ch;
int ret = 0;
- if (bpmp_init_state != BPMP_INIT_COMPLETE) {
+ if (bpmp_init_state == BPMP_INIT_PENDING) {
/* check if the bpmp processor is alive. */
- val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
- if (val != SIGN_OF_LIFE) {
- return -ENOTSUP;
- }
+ do {
+ val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+ if (val != SIGN_OF_LIFE) {
+ mdelay(1);
+ timeout--;
+ }
- /* check if clock for the atomics block is enabled */
- val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V);
- if ((val & CAR_ENABLE_ATOMICS) == 0) {
- ERROR("Clock to the atomics block is disabled\n");
- }
+ } while ((val != SIGN_OF_LIFE) && (timeout > 0U));
- /* check if the atomics block is out of reset */
- val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V);
- if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) {
- ERROR("Reset to the atomics block is asserted\n");
- }
+ if (val == SIGN_OF_LIFE) {
- /* base address to get the result from Atomics */
- base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET;
+ /* check if clock for the atomics block is enabled */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V);
+ if ((val & CAR_ENABLE_ATOMICS) == 0) {
+ ERROR("Clock to the atomics block is disabled\n");
+ }
- /* channel area is setup by BPMP before signaling handshake */
- for (ch = 0; ch < NR_CHANNELS; ch++) {
+ /* check if the atomics block is out of reset */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V);
+ if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) {
+ ERROR("Reset to the atomics block is asserted\n");
+ }
- /* issue command to get the channel base address */
- mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) |
- ATOMIC_CMD_GET);
+ /* base address to get the result from Atomics */
+ base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET;
- /* get the base address for the channel */
- channel_base[ch] = mmio_read_32(base);
+ /* channel area is setup by BPMP before signaling handshake */
+ for (ch = 0; ch < NR_CHANNELS; ch++) {
- /* increment result register offset */
- base += 4U;
- }
+ /* issue command to get the channel base address */
+ mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) |
+ ATOMIC_CMD_GET);
- /* mark state as "initialized" */
- bpmp_init_state = BPMP_INIT_COMPLETE;
+ /* get the base address for the channel */
+ channel_base[ch] = mmio_read_32(base);
- /* the channel values have to be visible across all cpus */
- flush_dcache_range((uint64_t)channel_base, sizeof(channel_base));
- flush_dcache_range((uint64_t)&bpmp_init_state,
- sizeof(bpmp_init_state));
+ /* increment result register offset */
+ base += 4U;
+ }
+
+ /* mark state as "initialized" */
+ bpmp_init_state = BPMP_INIT_COMPLETE;
+
+ /* the channel values have to be visible across all cpus */
+ flush_dcache_range((uint64_t)channel_base,
+ sizeof(channel_base));
+ flush_dcache_range((uint64_t)&bpmp_init_state,
+ sizeof(bpmp_init_state));
+
+ INFO("%s: done\n", __func__);
- INFO("%s: done\n", __func__);
+ } else {
+ ERROR("BPMP not powered on\n");
+ ret = -ETIMEDOUT;
+ }
}
return ret;
}
+
+void tegra_bpmp_suspend(void)
+{
+ /* freeze the interface */
+ bpmp_init_state = BPMP_SUSPEND_ENTRY;
+ flush_dcache_range((uint64_t)&bpmp_init_state, sizeof(bpmp_init_state));
+}
+
+void tegra_bpmp_resume(void)
+{
+ uint32_t val, timeout = 0;
+
+ if (bpmp_init_state == BPMP_SUSPEND_ENTRY) {
+
+ /* check if the bpmp processor is alive. */
+ do {
+
+ val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+ if (val != SIGN_OF_LIFE) {
+ mdelay(1);
+ timeout++;
+ }
+
+ } while ((val != SIGN_OF_LIFE) && (timeout < BPMP_TIMEOUT));
+
+ if (val == SIGN_OF_LIFE) {
+
+ INFO("%s: BPMP took %d ms to resume\n", __func__, timeout);
+
+ /* mark state as "initialized" */
+ bpmp_init_state = BPMP_INIT_COMPLETE;
+
+ /* state has to be visible across all cpus */
+ flush_dcache_range((uint64_t)&bpmp_init_state,
+ sizeof(bpmp_init_state));
+ } else {
+ ERROR("BPMP not powered on\n");
+ }
+ }
+}